package cn.iocoder.yudao.module.mqtt.service.devicegroup;

import cn.hutool.core.collection.CollUtil;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import cn.iocoder.yudao.module.mqtt.controller.admin.devicegroup.vo.*;
import cn.iocoder.yudao.module.mqtt.dal.dataobject.devicegroup.DeviceGroupDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.mqtt.dal.mysql.devicegroup.DeviceGroupMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList;
import static cn.iocoder.yudao.module.mqtt.enums.ErrorCodeConstants.*;

/**
 * 设备分组 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class DeviceGroupServiceImpl implements DeviceGroupService {

    @Resource
    private DeviceGroupMapper deviceGroupMapper;

    @Override
    public Long createDeviceGroup(DeviceGroupSaveReqVO createReqVO) {
        // 校验父级ID的有效性
        validateParentDeviceGroup(null, createReqVO.getParentId());
        // 校验分组名字的唯一性
        validateDeviceGroupNameUnique(null, createReqVO.getParentId(), createReqVO.getName());

        // 插入
        DeviceGroupDO deviceGroup = BeanUtils.toBean(createReqVO, DeviceGroupDO.class);
        deviceGroupMapper.insert(deviceGroup);
        // 返回
        return deviceGroup.getId();
    }

    @Override
    public void updateDeviceGroup(DeviceGroupSaveReqVO updateReqVO) {
        // 校验存在
        validateDeviceGroupExists(updateReqVO.getId());
        // 校验父级ID的有效性
        validateParentDeviceGroup(updateReqVO.getId(), updateReqVO.getParentId());
        // 校验分组名字的唯一性
        validateDeviceGroupNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());

        // 更新
        DeviceGroupDO updateObj = BeanUtils.toBean(updateReqVO, DeviceGroupDO.class);
        deviceGroupMapper.updateById(updateObj);
    }

    @Override
    public void deleteDeviceGroup(Long id) {
        // 校验存在
        validateDeviceGroupExists(id);
        // 校验是否有子设备分组
        if (deviceGroupMapper.selectCountByParentId(id) > 0) {
            throw exception(DEVICE_GROUP_EXITS_CHILDREN);
        }
        // 删除
        deviceGroupMapper.deleteById(id);
    }


    private void validateDeviceGroupExists(Long id) {
        if (deviceGroupMapper.selectById(id) == null) {
            throw exception(DEVICE_GROUP_NOT_EXISTS);
        }
    }

    private void validateParentDeviceGroup(Long id, Long parentId) {
        if (parentId == null || DeviceGroupDO.PARENT_ID_ROOT.equals(parentId)) {
            return;
        }
        // 1. 不能设置自己为父设备分组
        if (Objects.equals(id, parentId)) {
            throw exception(DEVICE_GROUP_PARENT_ERROR);
        }
        // 2. 父设备分组不存在
        DeviceGroupDO parentDeviceGroup = deviceGroupMapper.selectById(parentId);
        if (parentDeviceGroup == null) {
            throw exception(DEVICE_GROUP_PARENT_NOT_EXITS);
        }
        // 3. 递归校验父设备分组，如果父设备分组是自己的子设备分组，则报错，避免形成环路
        if (id == null) { // id 为空，说明新增，不需要考虑环路
            return;
        }
        for (int i = 0; i < Short.MAX_VALUE; i++) {
            // 3.1 校验环路
            parentId = parentDeviceGroup.getParentId();
            if (Objects.equals(id, parentId)) {
                throw exception(DEVICE_GROUP_PARENT_IS_CHILD);
            }
            // 3.2 继续递归下一级父设备分组
            if (parentId == null || DeviceGroupDO.PARENT_ID_ROOT.equals(parentId)) {
                break;
            }
            parentDeviceGroup = deviceGroupMapper.selectById(parentId);
            if (parentDeviceGroup == null) {
                break;
            }
        }
    }

    private void validateDeviceGroupNameUnique(Long id, Long parentId, String name) {
        DeviceGroupDO deviceGroup = deviceGroupMapper.selectByParentIdAndName(parentId, name);
        if (deviceGroup == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的设备分组
        if (id == null) {
            throw exception(DEVICE_GROUP_NAME_DUPLICATE);
        }
        if (!Objects.equals(deviceGroup.getId(), id)) {
            throw exception(DEVICE_GROUP_NAME_DUPLICATE);
        }
    }

    @Override
    public DeviceGroupDO getDeviceGroup(Long id) {
        return deviceGroupMapper.selectById(id);
    }

    @Override
    public List<DeviceGroupDO> getDeviceGroupList(DeviceGroupListReqVO listReqVO) {
        return deviceGroupMapper.selectList(listReqVO);
    }

}